import 'dart:ffi';

import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'package:flutter_module/beans/data_layer_bean.dart';
import 'package:flutter_module/map/models/library_models.dart';
import 'package:flutter_module/map/models/ni_raster_tile_layer_model.dart';
import 'package:provider/provider.dart';

import 'dispatcher/ni_map_dispatcher_factory.dart';
import 'ni_map_method_channel_handler.dart';
import 'ni_types.dart';

/// 地图通信中心
class NIMapController {
  /// 通信
  late MethodChannel _mapChannel;

  late NIMapMethodChannelHandler _methodChannelHandler;

  NIMapController.withId(int id) {
    _init(id);
  }

  void _init(int id) {
    _mapChannel = MethodChannel('com.navinfo.collect/mapView_$id');
    _methodChannelHandler = NIMapMethodChannelHandler();
    _mapChannel.setMethodCallHandler(_handlerMethod);
  }

  /// 地图代理回调
  ///
  /// native -> flutter
  Future<dynamic> _handlerMethod(MethodCall call) async {
    return await _methodChannelHandler.handlerMethod(call);
  }

  ///用户操作过地图的状态
  void setMapEventCallback(NIMapEventCallback callback) {
    _methodChannelHandler.setMapEventCallback(callback);
  }

  ///用户单击地图获取点击坐标
  void setMapOnClickCallback(NIMapOnClickCallback callback) {
    _methodChannelHandler.setMapOnClickCallback((callback));
  }
}

///地图基础操作
extension BaseControlExtension on NIMapController {
  ///刷新地图
  Future upDateMap({bool redraw = false}) async {
    await NIMapDispatcherFactory.instance.baseDispatcher
        .updateMap(_mapChannel, redraw: redraw);
  }
}

extension ViewportExtension on NIMapController {
  ///设置地图中心点偏移
  Future setMapViewCenter(num xPivot, num yPivot) async {
    return await NIMapDispatcherFactory.instance.viewportDispatcher
        .setMapViewCenter(_mapChannel, xPivot, yPivot);
  }

  ///获取几何的外接矩形,返回矩形的左上，右下两个坐标
  ///wkt格式的矩形
  Future<String> getBoundingBoxWkt(NIGeoPoint geoPoint,
      {SnapType snapType = SnapType.SNAP_PIXEL, int distance = 50}) async {
    return await NIMapDispatcherFactory.instance.viewportDispatcher
        .getBoundingBoxWkt(_mapChannel, geoPoint,
            snapType: snapType, distance: distance);
  }
}

///marker操作
extension MarkerExtension on NIMapController {
  ///
  /// 在地图上添加marker
  /// [coordinate] 经纬度坐标 [pixel]屏幕像素 这两个都没有就用地图中心坐标
  /// [id] marker 标题
  /// [description] 描述信息
  Future<NIMarker?> addMarker(
      {NIGeoPoint? geoPoint,
      Offset? pixel,
      String? description = "",
      String id = ""}) async {
    return await NIMapDispatcherFactory.instance.markerDispatcher.addMarker(
        _mapChannel,
        geoPoint: geoPoint,
        pixel: pixel,
        id: id,
        description: description);
  }

  Future<bool?> removeMarker(String id) async {
    return await NIMapDispatcherFactory.instance.markerDispatcher
        .removeMarker(_mapChannel, id);
  }
}

/// 地图相关操作
extension AnimationExtension on NIMapController {
  /// flutter -> native 向原生发送命令

  /// 按像素移动地图中心点(Android独有)
  ///
  /// xPixel 水平方向移动像素数
  ///
  /// yPixel 垂直方向移动像素数
  ///
  /// animateDurationMs 动画更新时间
  ///
  /// bool 成功返回true 失败false
  Future<bool> animateToPixel(num xPixel, num yPixel,
      {int? animateDurationMs = 200}) async {
    return await NIMapDispatcherFactory.instance.animationDispatcher
        .animateToPixel(_mapChannel, xPixel, yPixel,
            animateDurationMs: animateDurationMs);
  }

  /// flutter -> native 向原生发送命令

  /// 按经纬度动地图中心点(Android独有)
  ///
  /// latitude 水平方向移动像素数
  ///
  /// longitude 垂直方向移动像素数
  ///
  /// animateDurationMs 动画更新时间
  ///
  /// bool 成功返回true 失败false
  Future<bool> animateToLatLon(double latitude, double longitude,
      {int? animateDurationMs = 200}) async {
    return await NIMapDispatcherFactory.instance.animationDispatcher
        .animateToLatLon(_mapChannel, latitude, longitude,
            animateDurationMs: animateDurationMs);
  }

  ///地图缩小
  Future zoomOut() async {
    await NIMapDispatcherFactory.instance.animationDispatcher
        .zoomOut(_mapChannel);
  }

  ///地图放大
  Future zoomIn() async {
    await NIMapDispatcherFactory.instance.animationDispatcher
        .zoomIn(_mapChannel);
  }
}

/// 定位信息相关操作
extension LocationExtension on NIMapController {
  /// flutter -> native 向原生发送命令

  /// 实时更新定位信息
  Future<bool?> updateLocationData(NILocation location,
      {bool tracking = true}) async {
    return await NIMapDispatcherFactory.instance.locationDispatcher
        .updateLocationData(_mapChannel, location, tracking: tracking);
  }
}

/// 线 数据的相关操作
extension LineExtension on NIMapController {
  /// flutter -> native 向原生发送命令

  ///增加 线数据的 点
  ///[pixel]屏幕像素
  Future<List<NIGeoPoint>?> addDrawLinePoint() async {
    return await NIMapDispatcherFactory.instance.lineDispatcher
        .addDrawLinePoint(_mapChannel);
  }

  Future cleanDrawLine() async {
    return await NIMapDispatcherFactory.instance.lineDispatcher
        .cleanDrawLine(_mapChannel);
  }
}

/// 面 数据的相关操作
extension PolygonExtension on NIMapController {
  /// flutter -> native 向原生发送命令

  ///增加 面数据的 点
  ///[pixel]屏幕像素
  Future<List<NIGeoPoint>?> addDrawPolygonPoint() async {
    return await NIMapDispatcherFactory.instance.polygonDispatcher
        .addDrawPolygonPoint(_mapChannel);
  }

  ///清空polygon的绘制
  Future cleanDrawPolygon() async {
    return await NIMapDispatcherFactory.instance.polygonDispatcher
        .cleanDrawPolygon(_mapChannel);
  }
}

///LayerManager操作
extension LayerManagerExtension on NIMapController {
  ///
  /// 切换底图
  /// [url] 地址
  /// [tilePath] 路徑
  /// [cache] 是否緩存
  Future<Bool?> switchRasterTileLayer({
    @required String? url,
    @required String? tilePath,
    bool? cache = false,
  }) async {
    return await NIMapDispatcherFactory.instance.layerManagerDispatcher
        .switchRasterTileLayer(_mapChannel,
            url: url, tilePath: tilePath, cache: cache);
  }

  ///
  /// 删除底图
  /// [url] 地址
  Future<bool?> removeRasterTileLayer(String url) async {
    return await NIMapDispatcherFactory.instance.layerManagerDispatcher
        .removeRasterTileLayer(_mapChannel, url);
  }

  ///
  /// 获取支持的默认底图集合
  /// [url] 地址
  Future<List<NIRasterTileLayer>> getRasterTileLayerList() async {
    return await NIMapDispatcherFactory.instance.layerManagerDispatcher
        .getRasterTileLayerList(_mapChannel);
  }
}
